package com.softserveinc.ita.kaiji.web.controller;

import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import com.softserveinc.ita.kaiji.dto.GameInfoDto;
import com.softserveinc.ita.kaiji.model.User;
import com.softserveinc.ita.kaiji.model.UserImpl;
import com.softserveinc.ita.kaiji.model.game.GameInfo;
import com.softserveinc.ita.kaiji.service.GameService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import com.softserveinc.ita.kaiji.model.player.bot.Bot;
import com.softserveinc.ita.kaiji.service.GameServiceImpl;

import java.io.IOException;


/**
 * Controller for New Game form
 * @author Boiko Eduard, Ievgen Sukhov
 * @version 2.0
 * @since 17.03.14 
 */


@Controller
@RequestMapping("/game/new")
@SessionAttributes("personId")
public class CreateGameController {

    private final long TURN_TIMEOUT = 60000L;
    private static Logger logger = Logger.getLogger(CreateGameController.class);

    @Autowired
    private GameService gameService;

    @RequestMapping(method = RequestMethod.GET)
    public String sendToForm(Model model, HttpServletResponse response){
    	
			logger.trace("CreateGameController got GET-request");
        
        GameInfoDto gameInfoDtoImpl = new GameInfoDto();
        gameInfoDtoImpl.setGameName("Duel");
        gameInfoDtoImpl.setPlayerName("Zoro");
        gameInfoDtoImpl.setNumberOfCards(3);
        gameInfoDtoImpl.setBotType(Bot.Types.MEDIUM);
        model.addAttribute("gameInfo", gameInfoDtoImpl);
        model.addAttribute("personId", new Integer(0));
		
			logger.trace("gameInfoDtoImpl added to the model and will be sent to form");
    	
        return "create-game";
    }

    @RequestMapping(method = RequestMethod.POST)
    public String initForm(@ModelAttribute("gameInfo") @Valid GameInfoDto gameInfoDto,
                           BindingResult br, HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {

        final AsyncContext asyncContext = request.startAsync(request, response);
        asyncContext.setTimeout(TURN_TIMEOUT);

        logger.trace("Checkin BindingResult for mistakes");

        if (br.hasErrors()) {
            logger.info("Registration failed: gameInfo model NOT VALID");
           return "create-game";
        }

        Integer gameId = gameService.createGame(gameInfoDto);
        asyncContext.start(new secondPlayerCheker(asyncContext, gameId, gameService));

        logger.trace("Game created. gameId will be passed to PlayGameController");

        Integer playerId = gameService.getPlayerIdFromGame(gameId);
        model.addAttribute("personId", playerId);
        logger.trace("Player_temp id added to cookies (personId)");

       return "redirect:/game/" + gameId + "/";

    }

    @RequestMapping(value = "join", method = RequestMethod.GET)
    public String joinGame(@RequestParam String gameName, @RequestParam String playerName, Model model) {
        User user = new UserImpl(playerName);
        gameService.addPlayer(user, gameName);
        Integer gameId = gameService.getGameId(gameName);
        Integer playerId = gameService.getPlayerIdFromGame(playerName, gameName);
        model.addAttribute("personId", playerId);
        return "redirect:/game/" + gameId + "/";
    }
}


class secondPlayerCheker implements Runnable {


    private GameService gameService;
    AsyncContext asyncContext;
    GameInfo info;
    Integer gameId;

    public secondPlayerCheker(AsyncContext asyncContext, Integer gameId, GameService gameService) {
        this.asyncContext = asyncContext;
       this.gameId = gameId;
        this.gameService = gameService;
    }

    @Override
    public void run() {

        try {
            info = gameService.getGameInfo(gameId);
           while(info.getPlayers().size() < 2) {
               info = gameService.getGameInfo(gameId);
            Thread.sleep(3000);
           }
        } catch (InterruptedException e) {
            e.printStackTrace();

    }
        asyncContext.complete();
  }
}

